const simpleGit = require('simple-git');
const fs = require('fs-extra');
const path = require('path');
const logger = require('../utils/logger');
const config = require('../config/default.json');
const PathUtils = require('../utils/pathUtils');

class GitService {
  constructor() {
    this.repoPath = PathUtils.resolveConfigPath(config.git.localPath);
  }

  /**
   * 智能拉取代码
   * 1. 判断是否首次拉取，如果本地无项目直接clone
   * 2. 如本地有代码则查看是否有修改，有修改则全部丢弃
   * 3. 判断本地head和远程head是否均为目标分支，如是同步项目的提交，拉取到本地
   */
  async pullCode(deployId, pushData) {
    const repoUrl = config.git.repositoryUrl || pushData.repository?.clone_url;
    
    if (!repoUrl) {
      throw new Error('未配置仓库URL');
    }

    logger.info('开始拉取代码', { deployId, repoUrl, targetBranch: config.git.targetBranch });

    // 验证认证配置
    const authValidation = await this.validateAuthConfig();
    if (!authValidation.valid) {
      throw new Error(`认证配置无效: ${authValidation.message}`);
    }

    // 确保父目录存在
    await fs.ensureDir(PathUtils.dirname(this.repoPath));
    
    // 配置Git选项
    const gitOptions = this.getGitOptions();
    
    // 检查是否首次拉取
    const isFirstTime = !(await fs.pathExists(PathUtils.join(this.repoPath, '.git')));
    
    if (isFirstTime) {
      await this.cloneRepository(repoUrl, gitOptions);
    } else {
      await this.updateRepository(gitOptions);
    }

    logger.info('代码拉取完成', { deployId });
  }

  /**
   * 首次克隆仓库
   */
  async cloneRepository(repoUrl, gitOptions) {
    logger.info('首次拉取，克隆仓库', { repoUrl, targetBranch: config.git.targetBranch });
    
    // 清理可能存在的文件
    await fs.remove(this.repoPath);
    
    const git = simpleGit(gitOptions);
    const authenticatedUrl = this.getAuthenticatedUrl(repoUrl);
    
    await git.clone(authenticatedUrl, this.repoPath, [
      '--branch', config.git.targetBranch,
      '--single-branch'
    ]);
  }

  /**
   * 更新现有仓库
   */
  async updateRepository(gitOptions) {
    logger.info('更新现有仓库', { targetBranch: config.git.targetBranch });
    
    const git = simpleGit(this.repoPath, gitOptions);
    
    // 检查当前分支
    const status = await git.status();
    const currentBranch = status.current;
    
    logger.info('当前仓库状态', { 
      currentBranch, 
      targetBranch: config.git.targetBranch,
      hasChanges: status.files.length > 0
    });

    // 如果有本地修改，丢弃所有修改
    if (status.files.length > 0) {
      logger.info('发现本地修改，丢弃所有修改');
      await git.reset(['--hard']);
      await git.clean('f', ['-d']);
    }

    // 获取远程信息
    await git.fetch(['origin']);
    
    // 检查是否在目标分支上
    if (currentBranch !== config.git.targetBranch) {
      logger.info('切换到目标分支', { from: currentBranch, to: config.git.targetBranch });
      
      // 尝试切换到目标分支
      try {
        await git.checkout(config.git.targetBranch);
      } catch (error) {
        // 如果本地没有该分支，从远程创建
        logger.info('本地不存在目标分支，从远程创建', { targetBranch: config.git.targetBranch });
        await git.checkout(['-b', config.git.targetBranch, `origin/${config.git.targetBranch}`]);
      }
    }

    // 检查本地和远程的HEAD是否一致
    const localHead = await git.revparse(['HEAD']);
    const remoteHead = await git.revparse([`origin/${config.git.targetBranch}`]);
    
    if (localHead !== remoteHead) {
      logger.info('本地和远程HEAD不一致，同步代码', { 
        localHead: localHead.substring(0, 8), 
        remoteHead: remoteHead.substring(0, 8) 
      });
      
      // 强制同步到远程HEAD
      await git.reset(['--hard', `origin/${config.git.targetBranch}`]);
    } else {
      logger.info('本地和远程HEAD一致，无需同步');
    }
  }

  /**
   * 获取Git配置选项
   */
  getGitOptions() {
    const options = {};
    
    if (config.git.auth.enabled) {
      if (config.git.auth.type === 'ssh' && config.git.auth.sshKeyPath) {
        // SSH密钥认证
        const sshKeyPath = path.resolve(config.git.auth.sshKeyPath);
        options.config = [
          `core.sshCommand=ssh -i "${sshKeyPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null`
        ];
        logger.info('使用SSH密钥认证', { sshKeyPath });
      }
    }
    
    return options;
  }

  /**
   * 获取带认证信息的仓库URL
   */
  getAuthenticatedUrl(originalUrl) {
    if (!config.git.auth.enabled) {
      return originalUrl;
    }

    const auth = config.git.auth;
    
    if (auth.type === 'token' && auth.token) {
      // Token认证 (GitHub, GitLab, Gitee等)
      if (originalUrl.includes('github.com')) {
        return originalUrl.replace('https://github.com/', `https://${auth.token}@github.com/`);
      } else if (originalUrl.includes('gitlab.com')) {
        return originalUrl.replace('https://gitlab.com/', `https://oauth2:${auth.token}@gitlab.com/`);
      } else if (originalUrl.includes('gitee.com')) {
        return originalUrl.replace('https://gitee.com/', `https://${auth.token}@gitee.com/`);
      } else {
        // 通用Token认证方式
        const urlObj = new URL(originalUrl);
        if (urlObj.protocol === 'https:') {
          urlObj.username = auth.token;
          urlObj.password = 'x-oauth-basic';
          return urlObj.toString();
        }
      }
      logger.info('使用Token认证', { provider: this.getGitProvider(originalUrl) });
    } else if (auth.type === 'password' && auth.username && auth.password) {
      // 用户名密码认证
      const urlObj = new URL(originalUrl);
      urlObj.username = encodeURIComponent(auth.username);
      urlObj.password = encodeURIComponent(auth.password);
      logger.info('使用用户名密码认证', { username: auth.username });
      return urlObj.toString();
    }
    
    return originalUrl;
  }

  /**
   * 获取Git提供商类型
   */
  getGitProvider(url) {
    if (url.includes('github.com')) return 'GitHub';
    if (url.includes('gitlab.com')) return 'GitLab';
    if (url.includes('gitee.com')) return 'Gitee';
    if (url.includes('bitbucket.org')) return 'Bitbucket';
    return 'Unknown';
  }

  /**
   * 验证认证配置
   */
  async validateAuthConfig() {
    const auth = config.git.auth;
    
    if (!auth.enabled) {
      return { valid: true, message: '认证未启用' };
    }

    if (auth.type === 'ssh') {
      if (!auth.sshKeyPath) {
        return { valid: false, message: 'SSH密钥路径未配置' };
      }
      
      const sshKeyPath = PathUtils.resolveConfigPath(auth.sshKeyPath);
      if (!(await fs.pathExists(sshKeyPath))) {
        return { valid: false, message: `SSH密钥文件不存在: ${sshKeyPath}` };
      }
      
      // 检查SSH密钥文件权限（仅Unix系统）
      const OSUtils = require('../utils/osUtils');
      const permissionCheck = await OSUtils.checkFilePermissions(sshKeyPath, 0o600);
      if (!permissionCheck.valid && OSUtils.isUnix()) {
        logger.warn(`SSH密钥文件权限问题: ${permissionCheck.message}`);
        // 尝试自动修复权限
        const fixed = await OSUtils.setFilePermissions(sshKeyPath, 0o600);
        if (fixed) {
          logger.info('SSH密钥文件权限已自动修复为600');
        }
      }
      
      return { valid: true, message: 'SSH密钥配置有效' };
    } else if (auth.type === 'token') {
      if (!auth.token) {
        return { valid: false, message: 'Token未配置' };
      }
      return { valid: true, message: 'Token配置有效' };
    } else if (auth.type === 'password') {
      if (!auth.username || !auth.password) {
        return { valid: false, message: '用户名或密码未配置' };
      }
      return { valid: true, message: '用户名密码配置有效' };
    }
    
    return { valid: false, message: '未知的认证类型' };
  }

  /**
   * 获取当前仓库信息
   */
  async getRepositoryInfo() {
    if (!(await fs.pathExists(path.join(this.repoPath, '.git')))) {
      return null;
    }

    try {
      const git = simpleGit(this.repoPath);
      const status = await git.status();
      const remotes = await git.getRemotes(true);
      const currentCommit = await git.revparse(['HEAD']);
      
      return {
        currentBranch: status.current,
        hasChanges: status.files.length > 0,
        remoteUrl: remotes[0]?.refs?.fetch || null,
        currentCommit: currentCommit.substring(0, 8),
        status: status.files
      };
    } catch (error) {
      logger.error('获取仓库信息失败', { error: error.message });
      return null;
    }
  }
}

module.exports = new GitService();